﻿using System;
using System.Collections.Generic;

namespace RedisDotNet
{
    /// <summary>
    /// Redis high level client
    /// </summary>
    public interface IRedisClient : IDisposable
    {
        #region Connection handling

        /// <summary>
        /// Disconnect from server.
        /// </summary>
        void Quit();

        /// <summary>
        /// Authenticate connection
        /// </summary>
        /// <param name="password">The password.</param>
        /// <returns>True if authentication successful.</returns>
        bool Authenticate(string password);

        #endregion

        #region All value commands

        /// <summary>
        /// Determines if the specified key exists
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns>Whether or not the key exists</returns>
        bool Exists(string key);

        /// <summary>
        /// Deletes the specified keys.
        /// </summary>
        /// <param name="keys">The keys.</param>
        /// <returns>The number of keys deleted</returns>
        int Delete(params string[] keys);

        /// <summary>
        /// Determines the type of the specified key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        RedisType Type(string key);

        /// <summary>
        /// Query key list with pattern.
        /// </summary>
        /// <param name="pattern">Query pattern</param>
        /// <returns>List of keys</returns>
        string[] Keys(string pattern);

        /// <summary>
        /// Return a random key from the server.
        /// </summary>
        /// <returns>A random key from the server or empty string if there are
        /// no keys</returns>
        string RandomKey();

        /// <summary>
        /// Rename a key
        /// </summary>
        /// <param name="originalKey">Original key name.</param>
        /// <param name="newKey">New key name.</param>
        /// <returns>True if successful</returns>
        bool Rename(string originalKey, string newKey);

        /// <summary>
        /// Rename a key safely, failing if the key already exists.
        /// </summary>
        /// <param name="originalKey">Original key name.</param>
        /// <param name="newKey">New key name.</param>
        /// <param name="failIfAlreadyExists">If true, fail if the new
        /// key already exists.</param>
        /// <returns>True if successful, False if already exists/orignal key 
        /// didn't exist.</returns>
        bool Rename(string originalKey, string newKey, bool failIfAlreadyExists);

        /// <summary>
        /// Get count of keys
        /// </summary>
        /// <returns>Total number of keys in the database</returns>
        int DbSize();

        /// <summary>
        /// Expire the key after a set time period in seconds
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="seconds">Time in seconds to expire</param>
        /// <returns>True if expiry request successful.</returns>
        bool Expire(string key, int seconds);

        /// <summary>
        /// Expire the key at a set time
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="at">Time at which to expire.</param>
        /// <returns>True if expiry request successful.</returns>
        bool Expire(string key, DateTime at);

        /// <summary>
        /// Get the time to live for the key in seconds
        /// </summary>
        /// <param name="key">They key.</param>
        /// <returns>Time in seconds, or -1 if key does not exist or doesn't 
        /// have an expiry set</returns>
        int TimeToLive(string key);

        /// <summary>
        /// Select a database.
        /// </summary>
        /// <param name="database">Database index to select.</param>
        /// <returns>True if successful.</returns>
        bool Select(int database);

        /// <summary>
        /// Move a key to a different database.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="targetDatabase">Target database index.</param>
        /// <returns></returns>
        bool Move(string key, int targetDatabase);

        /// <summary>
        /// Delete all keys in current database
        /// </summary>
        /// <returns>True if successful</returns>
        bool FlushDb();

        /// <summary>
        /// Delete all keys in all databases
        /// </summary>
        /// <returns>True if successful</returns>
        bool FlushAll();

        #endregion

        #region String commands

        /// <summary>
        /// Sets the specified key to a string value
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <returns>True if set was successful</returns>
        bool Set(string key, string value);

        /// <summary>
        /// Sets the specified key to a string value, failing if it already
        /// exists when failIfAlreadyExists is set.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <param name="failIfAlreadyExists">If true, fail if already exists.
        /// </param>
        /// <returns>True if successful.</returns>
        bool Set(string key, string value, bool failIfAlreadyExists);

        /// <summary>
        /// Set multiple keys and values.  Either completely succeeds or fails.
        /// </summary>
        /// <param name="data">Key value pair list</param>
        /// <returns>True if all keys set.  False if no key was set.</returns>
        bool Set(List<KeyValuePair<string, string>> data);

        /// <summary>
        /// Set multiple keys and values.  Either completely succeeds or fails.
        /// </summary>
        /// <param name="data">Key value pair list</param>
        /// <param name="failIfAlreadyExists">Fail if any key exist.</param>
        /// <returns>True if all keys set.  False if no key was set.</returns>
        bool Set(List<KeyValuePair<string, string>> data, bool failIfAlreadyExists);

        /// <summary>
        /// Gets the specified key as a string
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns>The specified key as a string</returns>
        string Get(string key);

        /// <summary>
        /// Get a key and set it to a new value in one transaction, returning
        /// the old key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <returns>The old value.</returns>
        string GetSet(string key, string value);

        /// <summary>
        /// Get multiple keys
        /// </summary>
        /// <param name="keys">The keys.</param>
        /// <returns>Array of returned keys.</returns>
        string[] Get(string[] keys);

        /// <summary>
        /// Increment key by one
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns>Value after increment operation.</returns>
        int Incr(string key);

        /// <summary>
        /// Increment key by specified value
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="by">The amount to increment the key by.</param>
        /// <returns>Value after increment operation.</returns>
        int Incr(string key, int by);

        /// <summary>
        /// Decrement key by one
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns>Value after decrement operation.</returns>
        int Decr(string key);

        /// <summary>
        /// Decrement key by one
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="by">The amount to decrement the key by.</param>
        /// <returns>Value after decrement operation.</returns>
        int Decr(string key, int by);

        #endregion

        #region List commands

        #endregion

        #region Set operations

        /// <summary>
        /// Add member to set defined by key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="member">The member.</param>
        /// <returns>True if successful</returns>
        bool SetAdd(string key, string member);

        /// <summary>
        /// Remove a member from set defined by key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="member">The member.</param>
        /// <returns>True if removed, False if didn't exist.</returns>
        bool SetRemove(string key, string member);

        /// <summary>
        /// Return whether or not the specified member is in the set
        /// defined by key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="member">The member.</param>
        /// <returns>True if is member of set.</returns>
        bool SetIsMember(string key, string member);

        #endregion

        #region Sorted set commands

        #endregion

        #region Hash commands

        #endregion

        #region Sorting

        #endregion

        #region Transactions

        #endregion

        #region Pub/sub commands

        #endregion

        #region Persistence control

        /// <summary>
        /// Save the whole data set to disk including keys due to expire.  This
        /// blocks the processes until complete so that no other requests will
        /// be handled.
        /// </summary>
        /// <returns>True if successful</returns>
        bool Save();

        #endregion

        #region Remote server control

        #endregion
    }
}
